#ifndef GENERICV_H
#define GENERICV_H

#include <stdarg.h>
#include <stdint.h>
#include <inttypes.h>

typedef enum {
  T_INT8,
  T_UINT8,
  T_INT16,
  T_UINT16,
  T_INT32,
  T_UINT32,
  T_INT64,
  T_UINT64,
  T_CHAR,
  T_UCHAR,
  T_SCHAR,
  T_SHORT,
  T_USHORT,
  T_SSHORT,
  T_INT,
  T_UINT,
  T_SINT,
  T_LONG,
  T_ULONG,
  T_SLONG,
  T_LONGLONG,
  T_ULONGLONG,
  T_SLONGLONG,
  T_FLOAT,
  T_DOUBLE,
  T_LONGDOUBLE,
  T_PCHAR,
  T_PTR
} etype;

typedef union
{
  int8_t		int8Val;
  uint8_t		uint8Val;

  int16_t		int16Val;
  uint16_t		uint16Val;

  int32_t		int32Val;
  uint32_t		uint32Val;

  int64_t		int64Val;
  uint64_t		uint64Val;

  char			charVal;
  signed char		scharVal;
  unsigned char		ucharVal;

  short			shortVal;
  signed short		sshortVal;
  unsigned short	ushortVal;

  int			intVal;
  signed int		sintVal;
  unsigned int		uintVal;

  long			longVal;
  signed long		slongVal;
  unsigned long		ulongVal;

  long long		longlongVal;
  signed long long	slonglongVal;
  unsigned long long	ulonglongVal;

  float			floatVal;
  double		doubleVal;
  long double		longdoubleVal;

  char			*pcharVal;
  void			*ptrVal;
} GenericVal;

void setValSTR(GenericVal *gVal, etype type, char *str);
char *getValSTR(GenericVal *gVal, etype type, char *strToRealloc);
void setValV(GenericVal *gVal, etype type, va_list a_list);
void setVal(GenericVal *gVal, etype type, ...);

#define INT8VAL val.int8Val
#define UINT8VAL val.uint8Val
#define INT16VAL val.int16Val
#define UINT16VAL val.int16Val
#define INT32VAL val.int32Val
#define UINT32VAL val.int32Val
#define INT64VAL val.int64Val
#define UINT64VAL val.int64Val
#define CHARVAL val.charVal
#define UCHARVAL val.ucharVal
#define SCHARVAL val.scharVal
#define SHORTVAL val.shortVal
#define USHORTVAL val.ushortVal
#define SSHORTVAL val.sshortVal
#define INTVAL val.intVal
#define UINTVAL val.uintVal
#define SINTTVAL val.sintVal
#define LONGVAL val.longVal
#define ULONGVAL val.ulongVal
#define SLONGTVAL val.slongVal
#define LONGLONGVAL val.longlongVal
#define ULONGLONGVAL val.ulonglongVal
#define SLONGLONGTVAL val.slonglongVal
#define FLOATVAL val.floatVal
#define DOUBLEVAL val.doubleVal
#define LONGDOUBLEVAL val.longdoubleVal
#define PCHARVAL val.pcharVal
#define PTRVAL val.ptrVal

typedef struct
{
  etype type;
  GenericVal val;
  char *strBuf;
  char isNull;
} GenericVar;

#define GVAR(type) {type, {0}, 0, 1}

void setVar(GenericVar *gVar, ...);
void setVarNull(GenericVar *gVar);
void setVarSTR(GenericVar *gVar, char *str);
int isVarNull(GenericVar *gVar);
char *getVarSTR(GenericVar *gVar);
void clearVar(GenericVar *gVar);
void delVar(GenericVar *gVar);

#endif
